/*
 * Scaffold Application Framework
 *
 * Copyright (c) 2010 Sii Sp. z o.o. All rights reserved.
 */

package com.rstrulak.dao;

import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.rstrulak.constant.GenericFilter;
import com.rstrulak.constant.PageInfo;
import com.rstrulak.constant.PresentationInfo;
import com.rstrulak.constant.SortField;
import com.rstrulak.core.dao.GenericDaoImpl;
import com.rstrulak.model.Permission;
import com.rstrulak.model.Role;

/**
 * RoleDao hibernate implementation.
 * 
 * @author Jakub Ciechan
 * @version 1.0
 */
@Repository("roleDao")
// TODO: Przemyslec
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public class RoleDaoImpl extends GenericDaoImpl<Role, Long> implements RoleDao {

    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("unchecked")
    // TODO: Sprawdzic czy to zadziala zgodnie z oczekiwaniami
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public List<Permission> getAllPermissions() {
        // return getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(Permission.class).addOrder(Order.asc("name")));
        return getSession().createCriteria(Permission.class).addOrder(Order.asc("name")).list();
    }
    
    public List<Permission> getPermisions(final PresentationInfo presentationInfo) {
        Criteria criteria = getSession().createCriteria(Permission.class);
        if(presentationInfo.isPagingIncluded()){
            applyPagingToCriteria(criteria, presentationInfo.getPageInfo());
        }
        if(presentationInfo.isSortingIncluded()){
            applySortingToCriteria(criteria, presentationInfo.getSortInfo());
        }
        return criteria.list();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Permission> getPermisions(final Long roleId, final PresentationInfo presentationInfo) {
        List<Permission> list = (List<Permission>) getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                StringBuilder hql = new StringBuilder();
                hql.append("select p from ").append(Role.class.getName()).append(" r ").append(
                        " join r.permissions p where r.id = :roleId ");
                if (presentationInfo.isSortingIncluded()) {
                    hql.append("order by ");
                    for (SortField sortField : presentationInfo.getSortInfo().getFields()) {
                        if (sortField.isOrderAscending()) {
                            hql.append("p.").append(sortField.getName());
                        } else {
                            hql.append("p.").append(sortField.getName()).append(" desc ");
                        }
                    }
                }
                Query query = getSession().createQuery(hql.toString());
                if (presentationInfo.isPagingIncluded()) {
                    Criteria criteria = getSession().createCriteria(Permission.class);
                    criteria.setProjection(Projections.rowCount());
                    Integer resultsCount = (Integer) criteria.uniqueResult();
                    PageInfo pageInfo = presentationInfo.getPageInfo();
                    pageInfo.setResultsCount(resultsCount);
                    pageInfo.setPagesCount((int) Math.ceil((double) resultsCount / pageInfo.getPageSize()));
                    query.setFirstResult(pageInfo.getPageNo());
                    query.setMaxResults(pageInfo.getPageSize());
                }
                query.setLong("roleId", roleId);
                return query.list();
            }
        });
        return list;
    }
    public int getPermissinCount(GenericFilter filter) {
        Criteria criteria = getSession().createCriteria(Permission.class);
        if (filter != null) {
            filter.addRestrictionFromFilterFields(criteria);
        }
        criteria.setProjection(Projections.rowCount());
        Integer resultsCount = (Integer) criteria.uniqueResult();
        return resultsCount;
    }
}
